home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 120_01.zip / XC.C < prev    next >
Text File  |  1993-06-01  |  22KB  |  806 lines

  1. /* HEADER: CUG120.25;
  2.    TITLE: XC;
  3.    VERSION: 1.0;
  4.    DATE: 00/00/1982;
  5.    DESCRIPTION: "A cross-reference utility for C-programs.
  6.     It has the ability to handle nested include files to
  7.     a depth of 8.";
  8.    KEYWORDS: C programming,concordance generator;
  9.    SYSTEM: CP/M;
  10.    FILENAME: XC.C;
  11.    CRC: 3D48;
  12.    AUTHORS: Phillip N. Hisley;
  13.    COMPILERS: BDS C;
  14. */
  15. /***********************************************************/
  16. /*                               */
  17. /*    XC  -  A 'C' Concordance Utility                     */
  18. /*                               */
  19. /*    Version 1.0   January, 1982               */
  20. /*                               */
  21. /*    Copyright (c) 1982 by Philip N. Hisley               */
  22. /*                               */
  23. /*    Released for non-commercial distribution only        */
  24. /*                               */
  25. /*    Abstract:                           */
  26. /*                                   */
  27. /*    'XC' is a cross-reference utility for 'C' programs.  */
  28. /*    Its has the ability to handle nested include files   */
  29. /*    to a depth of 8 levels and properly processes nested */
  30. /*    comments as supported by BDS C. Option flags support */
  31. /*    the following features:                   */
  32. /*                               */
  33. /*    - Routing of list output to disk               */
  34. /*    - Cross-referencing of reserved words           */
  35. /*    - Processing of nested include files           */
  36. /*    - Generation of listing only               */
  37. /*                               */
  38. /*    Usage: xc <filename> <flag(s)>               */
  39. /*                               */
  40. /*    Flags: -i            = Enable file inclusion         */
  41. /*           -l               = Generate listing only         */
  42. /*           -r            = Cross-ref reserved words      */
  43. /*           -o <filename> = Write output to named file    */
  44. /*                               */
  45. /*                               */
  46. /*    -------------------------------------------------    */
  47. /*                               */
  48. /*    Compiliation Instructions - BDS C V1.42           */
  49. /*                               */
  50. /*    XC.C utilizes the dynamic storage allocation         */
  51. /*    scheme provided by BDS C .. this option must be      */
  52. /*    enabled per the instructions in BDSCIO.H           */
  53. /*                                   */
  54. /*    The -o and the -e options are used to maximize        */
  55. /*    the execution speed of XC.               */
  56. /*                               */
  57. /*    cc1 xc.c -o -e3560                       */
  58. /*    clink xc -s -e3560                          */
  59. /*                               */
  60. /*    Note: The location of the externals (-e3560)       */
  61. /*        is valid for version 1.0 of XC.C .. any       */
  62. /*          changes to XC.C which increase the size        */
  63. /*          of the generated code will require that        */
  64. /*          -e <xxxx> be resized .. also use of a       */
  65. /*          version of BDS C other than V1.42 may          */
  66. /*          alter the location of the external data        */
  67. /*        .. handle with care!               */
  68. /*                               */
  69. /*        Resizing Procedure:                   */
  70. /*                                   */
  71. /*          1. Compile/link XC with -o option:           */
  72. /*                                      */
  73. /*           cc1 XC.C -o                   */
  74. /*           clink XC -s                   */
  75. /*                                   */
  76. /*           The link map will indicate the address       */
  77. /*           at which external data starts .. in the       */
  78. /*           case of XC V1.0/BDS C V1.42 this becomes    */
  79. /*           3821h                       */
  80. /*                               */
  81. /*        2. Re-compile/link XC with the -o option       */
  82. /*             and the -e option using the external       */
  83. /*             data address obtained from step 1.       */
  84. /*                               */
  85. /*           cc1 XC.C -o -e3821               */
  86. /*           clink XC -s -e3821               */
  87. /*                                 */
  88. /*        3. Use of the -e option in step 2 will cause   */
  89. /*           the size of the generated code to become    */
  90. /*           smaller .. re-compile/link adjusting the    */
  91. /*             external data address to just above the     */
  92. /*             end of the code.                   */
  93. /*                               */
  94. /*             cc1 XC.C -o -e3560               */
  95. /*             clink XC -s -e3560               */
  96. /*                               */
  97. /*    -------------------------------------------------    */
  98. /*                               */
  99. /*    Please report bugs/fixes/enhancements to:            */
  100. /*                               */
  101. /*            Philip N. Hisley                   */
  102. /*          548H Jamestown Court               */
  103. /*          Edgewood, Maryland 21040               */
  104. /*          (301) 679-4606                   */
  105. /*                                   */
  106. /*                                                      */
  107. /***********************************************************/
  108.  
  109. #include "bdscio.h"
  110.  
  111. #define  MAX_REF    5        /* maximum refs per ref-block */
  112. #define  MAX_LEN    20        /* maximum identifier length  */
  113. #define  MAX_WRD   749        /* maximum number of identifiers */
  114. #define  MAX_ALPHA  53          /* maximum alpha chain heads */
  115. #define  REFS_PER_LINE  8    /* maximum refs per line */
  116. #define    LINES_PER_PAGE 60
  117. #define FF 0x0C            /* formfeed */
  118.  
  119. struct  id_blk {
  120.          char  id_name[MAX_LEN];
  121.                struct id_blk *alpha_lnk;
  122.          struct rf_blk *top_lnk;
  123.          struct rf_blk *lst_lnk;
  124.                } oneid;
  125.  
  126. struct  rf_blk {
  127.                  int  ref_item[MAX_REF];
  128.           int  ref_cnt;
  129.                } onerf;
  130.  
  131. struct id_blk *id_vector[MAX_WRD];
  132.  
  133. struct alpha_hdr { struct id_blk *alpha_top;
  134.                    struct id_blk *alpha_lst;
  135.                  };
  136.  
  137. struct alpha_hdr alpha_vector[MAX_ALPHA];
  138.  
  139. int    linum;        /* line number */
  140. int    edtnum;        /* edit line number */
  141. int    fil_cnt;    /* active file index */
  142. int    wrd_cnt;    /* token count */
  143. int    pagno;        /* page number */
  144. int    id_cnt;        /* number of unique identifiers */
  145. int    rhsh_cnt;    /* number of conflict hits */
  146. int    filevl;        /* file level  */
  147. int    paglin;        /* page line counter */
  148. int    prt_ref;
  149. char    act_fil[MAX_LEN];
  150. char    lst_fil[MAX_LEN];
  151. char    gbl_fil[MAX_LEN];
  152. char    l_buffer[BUFSIZ];
  153. int    i_flg,o_flg,r_flg,l_flg;
  154.  
  155. main(argc,argv)
  156. int    argc;
  157. char    **argv;
  158.  
  159. {
  160.     char  *arg;
  161.  
  162.     if (argc < 2) use_err();
  163.     i_flg=r_flg=o_flg=l_flg=FALSE;
  164.     strcpy(gbl_fil,*++argv);
  165.     --argc;
  166.     if(gbl_fil[0] == '-')
  167.        use_err();
  168.     while(--argc != 0)
  169.      { if(*(arg=*++argv) == '-')
  170.         {switch(*++arg)
  171.          { case 'I': i_flg++;
  172.              break;
  173.            case 'R': r_flg++;
  174.              break;
  175.        case 'L':  l_flg++;
  176.                     break;
  177.            case 'O': { o_flg++;
  178.                if(--argc == 0) use_err();
  179.                        strcpy(lst_fil,*++argv);
  180.                        if(lst_fil[0] == '-') use_err();
  181.                 break;}
  182.            default: use_err();
  183.          }
  184.        }
  185.      else use_err();
  186.      }
  187.  
  188.      if(o_flg)
  189.        {if(fcreat(lst_fil,l_buffer) == ERROR)
  190.         { printf("ERROR: Unable to create list file - %s\n",lst_fil);
  191.           exit(0);}
  192.        printf("XC ... 'C' Concordance Utility  v1.0\n\n");
  193.         }
  194.  
  195.     _allocp = NULL;    /* initialize memory allocation pointer */
  196.     prt_ref = FALSE;
  197.     for(linum=0;linum < MAX_WRD;linum++) {
  198.        id_vector[linum] = NULL; }
  199.     for(linum=0;linum < MAX_ALPHA;linum++)
  200.      {
  201.        alpha_vector[linum].alpha_top =
  202.        alpha_vector[linum].alpha_lst = NULL;
  203.      }
  204.     fil_cnt = wrd_cnt = linum = 0;
  205.     filevl=paglin=pagno=edtnum=0;
  206.    id_cnt=rhsh_cnt=0;
  207.     proc_file(gbl_fil);
  208.     if(!l_flg) {
  209.       prnt_tbl();
  210.       printf("\nAllowable Symbols: %d\n",MAX_WRD);
  211.       printf("Unique    Symbols: %d\n",id_cnt);}
  212.     if(o_flg) {
  213.      nl();
  214.      if(fprintf(l_buffer,"%c",CPMEOF) == ERROR) lst_err();
  215.      fflush(l_buffer);
  216.      fclose(l_buffer);
  217.     }
  218. }
  219.  
  220. strcmp(s,t)
  221. char s[], t[];
  222. {
  223.   int i;
  224.   i=0;
  225.   while(s[i] == t[i])
  226.    if(s[i++] == '\0') return (0);
  227.   return (s[i]-t[i]);
  228. }
  229.  
  230. char *strcpy(s1,s2)
  231.   char *s1, *s2;
  232.   { char  *temp;
  233.     temp=s1;
  234.     while(*s1++ = *s2++);
  235.     return (temp);
  236.   }
  237.  
  238. lst_err()
  239.  
  240. { printf("\nERROR: Write error on list output file - %s\n",
  241.    lst_fil);
  242.   exit(0);
  243. }
  244.  
  245. use_err()
  246.  
  247.        { printf("\nERROR: Invalid parameter specification\n\n");
  248.        printf("Usage: xc <filename> <flag(s)>\n\n");
  249.        printf("Flags: -i            = Enable file inclusion\n");
  250.        printf("       -l         = Generate listing only\n");
  251.        printf("       -r            = Cross-reference reserved words\n");
  252.        printf("       -o <filename> = Write output to named file\n");
  253.        exit(0); }
  254.  
  255. proc_file(filnam)
  256.  
  257. char     *filnam;
  258.  
  259. {
  260.   char    *buffer;    /* allocated buffer pointer */
  261.   char  *sav_buffer;    /* saved alloc buffer pointer */
  262.   char    token[MAX_LEN];    /* token buffer */
  263.   int    eof_flg;    /* end-of-file indicator */
  264.   int    tok_len;    /* token length */
  265.   int    incnum;        /* included line number */
  266.   strcpy(act_fil,filnam);
  267.   if ((sav_buffer = buffer =  alloc(BUFSIZ)) == 0) {
  268.       printf("\nERROR: Unable to allocate file buffer for %s\n",filnam);
  269.       exit(0); }
  270.   if(fopen(filnam,buffer) == ERROR)
  271.       {printf("\nERROR: Unable to open input file: %s\n",filnam);
  272.         exit(0);}
  273.   if(filevl++ == 0) prt_hdr();
  274.   eof_flg = FALSE;
  275.   do { 
  276.        if(get_token(buffer,token,&tok_len,&eof_flg,0))
  277.          if(chk_token(token)) {
  278.            if(strcmp(token,"#include") == 0) 
  279.              if(get_token(buffer,token,&tok_len,&eof_flg,1))
  280.            if(!i_flg) continue;
  281.                  else
  282.         { incnum=edtnum;
  283.               edtnum=0;
  284.          nl();
  285.                 proc_file(token); 
  286.         edtnum=incnum;
  287.             strcpy(act_fil,filnam);
  288.            continue;}
  289.            put_token(token,linum);}
  290.      } while (!eof_flg);
  291.      
  292.      filevl -= 1;
  293.      fclose(buffer);
  294.      free(sav_buffer);
  295. }
  296.  
  297. get_token(g_buffer,g_token,g_toklen,g_eoflg,g_flg)
  298.  
  299. char    *g_buffer;
  300. char    *g_token;
  301. int    *g_toklen;
  302. int    *g_eoflg;
  303. int    g_flg;
  304.  
  305. /*
  306.     'getoken' returns the next valid identifier or
  307.     reserved word from a given file along with the
  308.     character length of the token and an end-of-file
  309.     indicator
  310. */
  311.  
  312. {
  313. int    c;
  314. char    *h_token;
  315. char    tmpchr;
  316.  
  317. h_token = g_token;
  318.  
  319. gtk:
  320. *g_toklen = 0;
  321. g_token = h_token;
  322.  
  323. /*
  324.     Scan and discard any characters until an alphabetic or
  325.     '_' (underscore) character is encountered or an end-of-file
  326.     condition occurs
  327. */
  328.  
  329. while((!isalpha(*g_token = rdchr(g_buffer,g_eoflg,g_flg))) && !*g_eoflg
  330.   && *g_token != '_' && *g_token != '0' && *g_token != '#');
  331. if(*g_eoflg) return(FALSE);
  332. *g_toklen += 1;
  333.  
  334. /*
  335.     Scan and collect identified alpanumeric token until
  336.     a non-alphanumeric character is encountered or and
  337.     end-of-file condition occurs
  338. */
  339.  
  340. if(g_flg) tmpchr = '.';
  341.      else tmpchr = '_';
  342. while((isalpha(c=rdchr(g_buffer,g_eoflg,g_flg)) ||
  343.        isdigit(c) || c == '_' || c == tmpchr) && !*g_eoflg)
  344.     { 
  345.          if(*g_toklen < MAX_LEN)
  346.       { *++g_token = c;
  347.       *g_toklen += 1; }
  348.     }
  349.  
  350. /*
  351.     Check to see if a numeric hex or octal constant has
  352.     been encountered ... if so dump it and try again
  353. */
  354.  
  355.     if (*h_token == '0') goto gtk;
  356.  
  357.  
  358. /*
  359.     Tack a NULL character onto the end of the token
  360. */
  361.  
  362.  *++g_token = NULL;
  363.  
  364. /*
  365.     Screen out all #token strings except #include
  366. */
  367.  
  368. if (*h_token == '#' && strcmp(h_token,"#include")) goto gtk;
  369.  
  370.  return(TRUE);
  371. }
  372.  
  373.  fil_chr(f_buffer,f_eof)
  374.    char *f_buffer;
  375.    int *f_eof;
  376.    { int fc;
  377.    fc=getc(f_buffer);
  378.    if(fc == ERROR) {
  379.      printf("\nERROR: Error while processing input file - %s\n",
  380.      act_fil);
  381.      exit(0);
  382.      }
  383.     if (fc == CPMEOF || fc == EOF) { *f_eof = TRUE;
  384.                            fc = NULL; }
  385.     return(fc);}
  386.  
  387.  
  388. rdchr(r_buffer,r_eoflg,rd_flg)
  389.  
  390. int    *r_eoflg;
  391. char    *r_buffer;
  392. int    rd_flg;
  393.  
  394. /*
  395.       'rdchr' returns the next valid character in a file
  396.     and an end-of-file indicator. A valid character is
  397.     defined as any which does not appear in either a
  398.     commented or a quoted string ... 'rdchr' will correctly
  399.     handle comment tokens which appear within a quoted
  400.     string
  401. */
  402.  
  403. {
  404. int    c;
  405. int    q_flg;        /* double quoted string flag */
  406. int    q1_flg;        /* single quoted string flag */
  407. int    cs_flg;        /* comment start flag */
  408. int    ce_flg;        /* comment end flag */
  409. int    c_cnt;        /* comment nesting level */
  410. int    t_flg;        /* transparency flag */
  411.  
  412. q_flg = FALSE;
  413. q1_flg = FALSE;
  414. cs_flg = FALSE;
  415. ce_flg = FALSE;
  416. t_flg = FALSE;
  417. c_cnt  = 0;
  418.  
  419. rch:
  420.  
  421. /*
  422.     Fetch character from file
  423. */
  424.  
  425. c=fil_chr(r_buffer,r_eoflg);
  426. if(*r_eoflg) return(c);   /* EOF encountered */
  427. if(c == '\n') 
  428.             nl();
  429.            else 
  430.                if(o_flg)
  431.         {if(fprintf(l_buffer,"%c",c) == ERROR)
  432.            lst_err();}
  433.            else
  434.                printf("%c",c);
  435.  
  436. if(rd_flg) return(c);
  437.  
  438. if(t_flg) { t_flg = !t_flg;
  439.         goto rch;}
  440.  
  441. if(c == '\\') { t_flg = TRUE;
  442.                 goto rch;}
  443. /* 
  444.     If the character is not part of a quoted string
  445.     check for and process commented strings...
  446.     nested comments are handled correctly but unbalanced
  447.     comments are not ... the assumption is made that
  448.     the syntax of the program being xref'd is correct
  449. */
  450.  
  451. if (!q_flg && !q1_flg) {
  452.      if (c == '*' && c_cnt && !cs_flg) { ce_flg = TRUE;
  453.                    goto rch;}
  454.      if (c == '/' && ce_flg) { c_cnt -= 1;
  455.                    ce_flg = FALSE;
  456.                    goto rch; }
  457.      ce_flg = FALSE;
  458.      if (c == '/') { cs_flg = TRUE;
  459.              goto rch; }
  460.      if (c == '*' && cs_flg) { c_cnt += 1;
  461.                    cs_flg = FALSE;
  462.                    goto rch; }
  463.      cs_flg = FALSE;
  464.      if (c_cnt) goto rch;
  465. }
  466.  
  467. /*
  468.     Check for and process quoted strings
  469. */
  470.  
  471. if ( c == '"' && !q1_flg) { q_flg =  !q_flg; /* toggle quote flag */
  472.              goto rch;}
  473. if (q_flg) goto rch;
  474.  
  475. if (c == '\'') { q1_flg = !q1_flg; /* toggle quote flag */
  476.         goto rch; }
  477. if (q1_flg) goto rch;
  478.  
  479. /*
  480.     Valid character ... return to caller
  481. */
  482.  
  483. return(c);
  484. }
  485.  
  486. chk_token(c_token)
  487. char    *c_token;
  488.  
  489. {
  490.   char  u_token[MAX_LEN];
  491.   int   i;
  492.  
  493.     {
  494.       if(r_flg) return(TRUE);
  495.       i = 0;
  496.       do { u_token[i] = toupper(c_token[i]); }
  497.          while (c_token[i++] != NULL);
  498.  
  499.       switch(u_token[0]) {
  500.     case 'A': if (strcmp(u_token,"AUTO") == 0) return(FALSE);
  501.           break;
  502.     case 'B': if (strcmp(u_token,"BREAK") == 0) return(FALSE);
  503.           break;
  504.     case 'C': if (strcmp(u_token,"CHAR") == 0) return (FALSE);
  505.           if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
  506.           if (strcmp(u_token,"CASE") == 0) return (FALSE);
  507.           break;
  508.     case 'D': if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
  509.           if(strcmp(u_token,"DO") == 0) return(FALSE);
  510.           if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
  511.           break;
  512.     case 'E': if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
  513.           if(strcmp(u_token,"ELSE") == 0) return(FALSE);
  514.           if(strcmp(u_token,"ENTRY") == 0) return(FALSE);
  515.           break;
  516.     case 'F': if(strcmp(u_token,"FLOAT") == 0) return(FALSE);
  517.           if(strcmp(u_token,"FOR") == 0) return(FALSE);
  518.           break;
  519.     case 'G': if(strcmp(u_token,"GOTO") == 0) return(FALSE);
  520.           break;
  521.     case 'I': if(strcmp(u_token,"INT") == 0) return(FALSE);
  522.           if(strcmp(u_token,"IF") == 0) return(FALSE);
  523.           break;
  524.     case 'L': if(strcmp(u_token,"LONG") == 0) return(FALSE);
  525.           break;
  526.     case 'R': if(strcmp(u_token,"RETURN") == 0) return(FALSE);
  527.           if(strcmp(u_token,"REGISTER") == 0) return(FALSE);
  528.           break;
  529.     case 'S': if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
  530.           if(strcmp(u_token,"SHORT") == 0) return(FALSE);
  531.           if(strcmp(u_token,"STATIC") == 0) return(FALSE);
  532.           if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
  533.           if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
  534.           break;
  535.     case 'T': if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
  536.           break;
  537.     case 'U': if(strcmp(u_token,"UNION") == 0) return(FALSE);
  538.           if(strcmp(u_token,"UNSIGNED") == 0) return(FALSE);
  539.           break;
  540.     case 'W': if(strcmp(u_token,"WHILE") == 0) return(FALSE);
  541.           break; }
  542.         }
  543.   return(TRUE);
  544. }
  545.  
  546. /*
  547.    Install parsed token and line reference in linked structure
  548. */
  549.  
  550. put_token(p_token,p_ref)
  551.  
  552. char *p_token;
  553. int  p_ref;
  554.  
  555. {
  556.   int  hsh_index;
  557.   int  i;
  558.   int  j;
  559.   int  d;
  560.   int  found;
  561.   struct id_blk *idptr;
  562.   struct rf_blk *rfptr;
  563.   struct id_blk *alloc_id();
  564.   struct rf_blk *alloc_rf();
  565.   struct rf_blk *add_rf();
  566.  
  567.   if(l_flg) return;
  568.   j=0;
  569.   for (i=0; p_token[i] != NULL; i++)  /* Hashing algorithm is far from */
  570.   {                      /* optimal but is adequate for a */
  571.       j = j * 10 + p_token[i];          /* memory-bound index vector!    */
  572.    }
  573.   hsh_index = abs(j) % MAX_WRD;
  574.   found = FALSE;
  575.   d = 1;
  576.   do {
  577.        idptr = id_vector[hsh_index];
  578.        if(idptr == NULL) {
  579.          id_cnt++;
  580.          idptr = id_vector[hsh_index] = alloc_id(p_token);
  581.          chain_alpha(idptr,p_token);
  582.          idptr->top_lnk = idptr->lst_lnk = alloc_rf(p_ref);
  583.          found = TRUE;
  584.        }
  585.        else
  586.        if(strcmp(p_token,idptr->id_name) == 0) {
  587.          idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
  588.            found = TRUE;
  589.          }
  590.        else
  591.        { hsh_index += d;
  592.          d += 2;
  593.          rhsh_cnt++;
  594.          if (hsh_index >= MAX_WRD)
  595.             hsh_index -= MAX_WRD;
  596.          if (d == MAX_WRD) {
  597.             printf("\nERROR: Symbol table overflow\n");
  598.             exit(0);
  599.          }
  600.        }
  601.       } while (!found);
  602. }
  603.  
  604. chain_alpha(ca_ptr,ca_token)
  605.  
  606. struct id_blk *ca_ptr;
  607. char  *ca_token;
  608.  
  609. {
  610.   char  c;
  611.   int   f;
  612.   struct id_blk *cur_ptr;
  613.   struct id_blk *lst_ptr;
  614.  
  615.   c = ca_token[0];
  616.   if(c == '_') c = 0;
  617.     else
  618.       isupper(c) ? c=1+((c-'A')*2) : c=2+((c-'a')*2);
  619.  
  620.   if(alpha_vector[c].alpha_top == NULL)
  621.     { alpha_vector[c].alpha_top =
  622.       alpha_vector[c].alpha_lst = ca_ptr;
  623.       ca_ptr->alpha_lnk = NULL;
  624.       return;
  625.     }
  626.  
  627. /* check to see if new id_blk should be inserted between
  628.    the alpha_vector header block and the first id_blk in
  629.    the current alpha chain
  630. */
  631.  
  632.  if(strcmp(alpha_vector[c].alpha_top->id_name,ca_token) >0)
  633.   {
  634.     ca_ptr->alpha_lnk=alpha_vector[c].alpha_top;
  635.     alpha_vector[c].alpha_top=ca_ptr;
  636.     return;
  637.   }
  638.  
  639.   if(strcmp(alpha_vector[c].alpha_lst->id_name,ca_token) < 0)
  640.     { alpha_vector[c].alpha_lst->alpha_lnk = ca_ptr;
  641.       ca_ptr->alpha_lnk = NULL;
  642.       alpha_vector[c].alpha_lst=ca_ptr;
  643.       return;
  644.     }
  645.  
  646.   cur_ptr = alpha_vector[c].alpha_top;
  647.   while(strcmp(cur_ptr->id_name,ca_token) < 0)
  648.    { lst_ptr = cur_ptr;
  649.      cur_ptr = lst_ptr->alpha_lnk;
  650.    }
  651.  
  652.   lst_ptr->alpha_lnk = ca_ptr;
  653.   ca_ptr->alpha_lnk = cur_ptr;
  654.   return;
  655. }
  656.  
  657. struct id_blk *alloc_id(aid_token)
  658.   char  *aid_token;
  659.  
  660.   {
  661.     int  ai;
  662.     struct id_blk *aid_ptr;
  663.  
  664.      if((aid_ptr = alloc(sizeof(oneid))) == 0) {
  665.        printf("\nERROR: Unable to allocate identifier block\n");
  666.        exit(0);
  667.      }
  668.      ai=0;
  669.      do {
  670.           aid_ptr->id_name[ai] = aid_token[ai];
  671.         } while (aid_token[ai++] != NULL);
  672.      return (aid_ptr);
  673. }
  674.  
  675. struct rf_blk *alloc_rf(arf_ref)
  676.  
  677.   int  arf_ref;
  678.  
  679.   {
  680.     int ri;
  681.     struct rf_blk *arf_ptr;
  682.  
  683.     if((arf_ptr = alloc(sizeof(onerf))) == 0) {
  684.       printf("\nERROR: Unable to allocate reference block\n");
  685.       exit(0);
  686.     }
  687.     arf_ptr->ref_item[0] = arf_ref;
  688.     arf_ptr->ref_cnt = 1;
  689.     for(ri=1;ri<MAX_REF;ri++)
  690.       arf_ptr->ref_item[ri] = NULL;
  691.     return (arf_ptr);
  692.   }
  693.  
  694. struct rf_blk *add_rf(adr_ptr,adr_ref)
  695.  
  696.   struct rf_blk *adr_ptr;
  697.   int adr_ref;
  698.  
  699.   {
  700.     struct rf_blk *tmp_ptr;
  701.  
  702.     tmp_ptr = adr_ptr;
  703.     if(adr_ptr->ref_cnt == MAX_REF) {
  704.       tmp_ptr = adr_ptr->ref_cnt = alloc_rf(adr_ref);
  705.     }
  706.     else
  707.     { adr_ptr->ref_item[adr_ptr->ref_cnt++] = adr_ref;
  708.     }
  709.     return (tmp_ptr);
  710.   }
  711.  
  712. prnt_tbl()
  713. {  int prf_cnt;
  714.    int pti;
  715.    int pref;
  716.    int lin_cnt;
  717.    struct id_blk *pid_ptr;
  718.    struct rf_blk *ptb_ptr;
  719.  
  720.   prt_ref = TRUE;
  721.   prt_hdr();
  722.   for (pti=0;pti<MAX_ALPHA;pti++)
  723.   { if ((pid_ptr = alpha_vector[pti].alpha_top) != NULL)
  724.       { do
  725.      { if(o_flg)
  726.          {if(fprintf(l_buffer,"%-14.13s: ",pid_ptr->id_name) == ERROR)
  727.             lst_err();}
  728.        else
  729.       printf("%-14.13s: ",pid_ptr->id_name);
  730.        ptb_ptr=pid_ptr->top_lnk;
  731.        lin_cnt=prf_cnt=0;
  732.        do { if(prf_cnt == MAX_REF)
  733.               { prf_cnt=0;
  734.                 ptb_ptr = ptb_ptr->ref_cnt;
  735.               }
  736.            if(ptb_ptr > MAX_REF)
  737.             {
  738.              if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0)
  739.         { if(o_flg)
  740.                  {if(fprintf(l_buffer,"%d\t",pref) == ERROR) lst_err();}
  741.                 else
  742.                 printf("%d\t",pref);
  743.              if (++lin_cnt == REFS_PER_LINE)
  744.             { nl();
  745.               if(o_flg)
  746.                       {if(fprintf(l_buffer,"\t\t") == ERROR) lst_err();}
  747.                       else
  748.               printf("\t\t");
  749.                       lin_cnt=0;
  750.                     }
  751.         }
  752.               } else pref=0;
  753.        } while (pref);
  754.     if (lin_cnt = 0)
  755.        nl();
  756.          else
  757.        { nl(); nl(); }
  758.          } while ((pid_ptr=pid_ptr->alpha_lnk) != NULL);
  759.       }
  760.    }
  761.  }
  762.  
  763. prt_hdr()
  764.  
  765. { if (pagno++ != 0)
  766.    if(o_flg)
  767.      {if(fprintf(l_buffer,"%c",FF) == ERROR) lst_err();}
  768.      else printf("%c",FF);
  769.   if(o_flg)
  770.    {if(fprintf(l_buffer,
  771.     "XC ... 'C' Concordance Utility : %s\t\t\t\t Page %d",
  772.      gbl_fil,pagno) == ERROR) lst_err();}
  773.   else
  774.    printf("XC ... 'C' Concordance Utility : %s\t\t\t\t Page %d",
  775.      gbl_fil,pagno);
  776.   if(o_flg)
  777.     {if(fprintf(l_buffer,"\n\n") == ERROR) lst_err();}
  778.     else     printf("\n\n");
  779.   nl();
  780.  paglin =3;
  781.  return;
  782. }
  783.  
  784. nl()
  785.  
  786. { if(o_flg)
  787.    {if(fprintf(l_buffer,"\n") == ERROR) lst_err();}
  788.     else
  789.   printf("\n");
  790.   if(++paglin == LINES_PER_PAGE) prt_hdr();
  791.     else
  792.   if(!prt_ref) {
  793.     if(o_flg)
  794.    {if(fprintf(l_buffer,"%-4.4d.%4.4d:\t",++linum,++edtnum) == ERROR) 
  795.           lst_err();}
  796.         else
  797.       printf("%-4.4d.%4.4d:\t",++linum,++edtnum);
  798.     if(o_flg) 
  799.       if(linum % 60 == 1) 
  800.          printf("\n<%d>\t",linum);
  801.           else
  802.          printf(".");}
  803.  return;
  804. }
  805.  
  806.         {if(fprintf(l_b